/*
 * Copyright 2007-2009 Perttu "celeron55" Ahola <celeron55@gmail.com>
 *
 * This file is part of jukuMagic.
 *
 * jukuMagic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jukuMagic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with jukuMagic.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef board_h_
#define board_h_

#include "muut.h"
#include "circuit.h"
#include <vector>

#define CMAXH 100
#define CMAXW 100

enum Side{
	RIGHT,
	LEFT
};

class Board{
private:
	bool valid;
	unsigned int width, height;
	Contentblock contents[CMAXH][CMAXW];
	int dconnnumcounter;
	vector<DConn> dconns;
	int wirenumcounter;
	vector<Wire> wires;
	vector<Part> parts;
	vector<WirePart> wparts;
	
	//vector<int> footnums_as_nfc;

	Circuit *circuitp;

	int additional_x_spacing;

	int BFindPartNumWithFootNum(int num);
	int BFindWirePartNumWithFootNum(int num);
	int BFindWireNumWithFootNum(int num);

	/*bool AddToNFClist(int num); //palauttaa tosi jos ei ollut vielä listalla
	bool IsOnNFClist(int num);*/
	
	int GetPartNFCleft(Part &part, unsigned int y);
	int GetPartNFCright(Part &part, unsigned int y);

	//Coord GetApproxBoardCentre();
	
	bool IsFreePlace(unsigned int x, unsigned int y, unsigned int w, unsigned int h,
			unsigned int freexspace);
	Coord FindFreePlace(unsigned int w, unsigned int h, unsigned int freexspace);
	/*Coord FindClosestPossibleFreePlace(vector<Coord> &fromcs, unsigned int w, unsigned int h,
			unsigned int freexspace, vector<Coord> &not_directly_connected_to);
	Coord FindClosestPossibleFreePlace(Coord fromc, unsigned int w, unsigned int h,
			unsigned int freexspace, Coord not_directly_connected_to);*/
	Coord FindClosestPossibleFreePlace(vector<Coord> &fromcs, unsigned int w, unsigned int h,
			unsigned int freexspace);
	Coord FindClosestPossibleFreePlace(Coord fromc, unsigned int w, unsigned int h,
			unsigned int freexspace);
	Coord FindFreePlaceWithMaxRoom(unsigned int w, unsigned int h);

	bool IsRouteClear(Coord c1, Coord c2);

	bool IsFreePlaceForPart(Part &part, unsigned int x, unsigned int y, int losen);
	Coord FindFreePlaceForPart(Part &part);
	vector<Coord> FindAllFreePlacesForPart(Part &part);

	Coord FindClosestPossibleFreePlaceForPart(Coord fromc, Part &part);
	Coord FindClosestPossibleFreePlaceForPart(vector<Coord> fromcs, Part &part);
	Coord FindHighestScoredFreePlaceForPart(Part &part);

	bool PutPart(Part &part);
	bool PutPartWithNFC(Part &part);
	bool PutPartSomewhere(Part &part);
	bool PutPartSomewhereNear(Part &part, Coord fromc);
	bool PutPartSomewhereNear(Part &part, vector<Coord> fromcs);
	bool PutPartSomewhereWithMaxRoom(Part &part);
	bool PutPartToBestScoredPlace(Part &part);
	
	bool PutWirePart(WirePart wp);
	bool PutWirePartWisely(WirePart wp, unsigned int partxpacing);

	bool PutWire(Wire wire);

	void ClearBlock(Coord c);
	bool MoveWirePartHead(unsigned int wpnum, Coord c_from, Coord c_to);
	bool MoveWireHead(unsigned int wnum, Coord c_from, Coord c_to);
	bool LameMoveWirePartHead(unsigned int wpnum, Coord c_from, Coord c_to);
	bool MovePart(unsigned int pnum, Coord c_to);
	/*bool MoveBlock(unsigned int w, unsigned int h, unsigned int x1, unsigned int y1,
			unsigned int x2, unsigned int y2)*/

	Coord FindFootNum(int num);

	bool CoordAreWPFootOrPointOrWireHead(Coord c);
	bool AllCoordAreWPFootOrPointOrWireHead(vector<Coord> cs);
	
	vector<Coord> GetDirectlyConnectedCoord(Coord c);
	//bool IsDirectlyConnected(Coord c1, Coord c2); //toimii, mutta turha
	void GetAllConnectedCoords(Coord c, vector<Coord> *alreadysearched);
	vector<Coord> GetConnectedCoord(Coord c);
	bool IsConnected(Coord c1, Coord c2);

	Coord GetRightHoleDirectlyConnectedToCoord(Coord c, bool allowblock);
	Coord GetLeftHoleDirectlyConnectedToCoord(Coord c, bool allowblock);
	Coord GetHoleDirectlyConnectedToCoord(Coord c, bool allowblock);
	Coord GetNearestHoleDirectlyConnectedToCoord(Coord, unsigned int, bool allowblock);
	bool CanConnectCoordDirectly(Coord, Coord);
	vector<Coord> GetAllDirectlyConnectableHoles(Coord);
	Coord GetOptimalHoleDirectlyConnectedToCoord(Coord fromcoords, Coord tocoords,
			bool allowblock);
	Coord GetHoleConnectedToCoord(Coord c, bool allowblock);
	/*Coord GetClosestPossibleHoleConnectedToCoord(Coord fromcoords, Coord tocoords,
			bool allowblock, vector<Coord> &not_directly_connected_to);*/
	Coord GetClosestPossibleHoleConnectedToCoord(Coord fromcoords, Coord tocoords,
			bool allowblock);

	bool ConnectCoordDirectly(Coord c1, Coord c2);
	bool ConnectCoord(Coord c1, Coord c2);

	double ConnectionScore(Coord c1, Coord c2);
	double ConnectionScore(Part &p, Coord c);

	//return values:
	//-1: error
	//0 : no error, did nothing
	//1 : no error, did something
	int OptimizeChunkOrders();
	int OptimizeConnectionPlaces();
	int StraightenVertically();
	int CleanEverything(bool do_places, bool do_orders, bool do_straighten);

	int RemoveUnnecessaryCuts();

	bool UpdateContent(void);
	void InformContentChanged(void);
	
	int CheckBlock(unsigned int x, unsigned int y, unsigned int partxspacing, bool put_wires, bool put_wireparts, bool put_wireparts_to_random);
	
public:
	Board();
	bool Generate(Circuit *circuitp_, unsigned int width, unsigned int height);
	Contentblock Content(unsigned int x, unsigned int y);
	Contentblock Content(Coord c);
	bool Valid();
	unsigned int Width();
	unsigned int Height();
	vector<Wire> GetWires();
	vector<Part> GetParts();
	vector<WirePart> GetWireParts();
	void Draw();
};


#endif

